/***************************************************************************
 *   Copyright (C) 2009 by Marian Skvarek   *
 *   skvarek.marian@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A TrackICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "CNote.h"
#include "CNoteView.h"

namespace easyscore
{
    namespace core
    {

        //Accessors
        void CNote::setAccidental ( const EAccidental& value )
        {
            if(mAccidental == value)
                return;

            mAccidental = value;

            if(hasView())
                mView->onAccidentalChanged();
        }

        void CNote::setIsActive(bool value)
        {
            if(mIsActive == value)
                return;

            mIsActive = value;

            if(hasView())
                mView->onActiveChanged();
        }

        CNote::CNote(int position)
        {
            mPosition = position;
            mAccidental = eAccidentalNone;
            mIsGhost = false;
            mIsActive = false;

            mView = 0;
        }

        void CNote::initialize()
        {

        }

        void CNote::clear()
        {
            destroyView();
        }

        CNote::~CNote()
        {
            clear();
        }



        //Public methods

        void CNote::remove()
        {
            mParentNoteGroup->removeNote(this);
        }

        NOTE_OCTAVE CNote::getOctave()
        {
            return getAbsolutePosition() / NOTE_POSITION_OCTAVE;
        }

        NOTE_PITCH CNote::getRelativePitch()
        {
            int tonePos = getAbsolutePosition() % NOTE_POSITION_OCTAVE;

            if(tonePos <= NOTE_POSITION_E)
                return tonePos*2;
            else
                return (tonePos*2) - 1;
        }

        NOTE_PITCH CNote::getAbsolutePitch()
        {
            return getOctave()*NOTE_PITCH_OCTAVE + getRelativePitch() + getAccidentalPitchShift();
        }

        NOTE_PITCH CNote::getAbsoluteNotePitch()
        {
            return getAbsolutePitch();
        }

        void CNote::updatePositionList()
        {
            mPositionList.zeros();

            const int pitch = getAbsoluteNotePitch();

            for(int i = 0; i < 4; ++i)
            {
                int pos = pitch - PITCHE3;
                if(pos > 0 && pos < FRETBOARD_SIZE)
                    mPositionList.set(pos - i,true);

                pos = pitch - PITCHA3;
                if( pos > 0 && pos < FRETBOARD_SIZE)
                    mPositionList.set(pos - i,true);

                pos = pitch - PITCHD4;
                if(pos > 0 && pos < FRETBOARD_SIZE)
                    mPositionList.set(pos - i,true);

                pos = pitch - PITCHG4;
                if(pos > 0 && pos < FRETBOARD_SIZE)
                    mPositionList.set(pos - i,true);

                pos = pitch - PITCHH4;
                if(pos > 0 && pos < FRETBOARD_SIZE)
                    mPositionList.set(pos - i,true);

                pos = pitch - PITCHE5;
                if(pos > 0 && pos < FRETBOARD_SIZE)
                    mPositionList.set(pos - i,true);
            }
        }

        NOTE_PITCH CNote::getAccidentalPitchShift()
        {
            switch(mAccidental)
            {
            case eAccidentalFlat: return -1;
            case eAccidentalSharp: return 1;
            default: return 0;
            }
        }

        void CNote::createView()
        {
            if(hasView())
                destroyView();

            mView = new CNoteView( this );
        }

        void CNote::destroyView()
        {
            if(hasView())
            {
                delete mView;
                mView = 0;
            }
        }

        void CNote::updateView()
        {
            if(hasView())
                mView->update();
        }

        //Protected methods
        NOTE_POSITION CNote::getAbsolutePosition()
        {
            return mPosition + getParentTrack()->getClef().getPitchShift();
        }

    }
}
